#!/usr/bin/env python

"""advcivtool.py -- Advanced Civilization Tool
Author: Chris Evans <khaydarian@gmail.com>

Select your civilization using number keys.  Use arrow keys to select
a technology, spacebar to add it.  Costs are automatically recalculated.

Use Ctrl-C to exit -- your data will not be saved!

Designed for linux console at 80x24 (doesn't resize for larger terminals).

"""

import curses, curses.wrapper

# List of the names displayed for the civilizations -- order is irrelevant,
# but should fit on one line.
CivNames = "Africa Italy Illyria Thrace Asia Bablyon Arabia Egypt Crete".split()

# List of all technology cards -- order must match matrix below
Cards = """
 45 C Pottery
 45 C Clothmaking
 80 C Metalworking
110 C Agriculture
140 C Roadbuilding
180 C Mining
140 CS Engineering
 80 S Astronomy
110 S Coinage
140 S Medicine
230 AS Mathematics
 60 A Drama/Poetry
 60 A Music
120 A Architecture
110 AV Literacy
170 V Law
200 V Democracy
180 V Military
240 V Philosophy
 50 AR Mysticism
 80 R Deism
150 R Enlightenment
220 R Monotheism
250 R Theology
"""

# List of pre-requsite technologies (indexes into above array)
Prereqs = [0,0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,15,0,15,0,0,0,21,21]

# Matrix of credits, copied from the instruction booklet
Credits = """
 0 10 10 10 10 10 10  0  0  0  0  0  0  0  0  0 10  0  0  0  0  0 10  0
10  0 10 10 10 10 10  0  0  0  0  0  0  0  0  0 10  0  0  0  0  0 10  0
10 10  0 10 10 10 10  0  0  0  0  0  0  0  0  0 10 20  0  0  0  0 10  0
10 10 10  0 10 10 10  0  0  0  0  0  0  0  0  0 10  0  0  0  0  0 10  0
10 10 10 10  0 10  0  0  0  0  0  0  0  0  0  0 10  0  0  0  0  0 10  0
10 10 10 10 10  0  0  0  0  0  0  0  0  0  0  0 10  0  0  0  0  0 10  0
10 10 10 10 10 10  0 20 20 20 20  0  0  0  0  0 10  0 20  0  0  0 10 20
 0  0  0  0  0  0 20  0 20 20 20  0  0  0  0  0  0  0 20  0  0  0  0 20
 0  0  0  0  0  0 20 20  0 20 20  0  0  0  0  0  0  0 20  0  0  0  0 20
 0  0  0  0  0  0 20 20 20  0 20  0  0  0  0  0  0  0 20  0  0  0  0 20
 0  0  0  0  0  0 20 20 20 20  0  5  5  5  5  5  0  0 25  5  0 10  0 25
 0  0  0  0  0  0  0  0  0  0  5  0  5  5 20  5 10  0  0  5  0 10  0  0
 0  0  0  0  0  0  0  0  0  0 20  5  0  5  5  5 10  0 20  5  0 10  0  0
 0  0  0  0  0  0  0  0  0  0  5  5  5  0  5 15 10  0  0  5  0 10  0  0
 0  0  0  0  0  0  0  0  0  0  5  5  5  5  0 25 25  0 25  5  0 10  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  5  5  5  5  5  0  0  0  0  0 15 15 15 15
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 15 15 15
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 15 15
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
"""

# Functional Craziness to calculate costs, and parse above strings
Cards = [(int(t[0]),t[1],t[2]) for t in map(str.split,Cards.strip().splitlines())] 
NumCards = len(Cards)
Credits = map(lambda line: map(int, line.split()), Credits.strip().splitlines())
Credits = [ [Credits[j][i] for j in xrange(len(Credits))] for i in xrange(len(Credits))]
Cards_namewidth = max([len(c[2]) for c in Cards])
def cost(idx): return Cards[idx][0]
def total(have): return sum([hv*cost(i) for i,hv in enumerate(have)])
def credit(idx,have): return sum([a*b for a,b in zip(have,Credits[idx])])

colors = [curses.COLOR_WHITE, curses.COLOR_GREEN, curses.COLOR_BLUE, curses.COLOR_RED, curses.COLOR_YELLOW, curses.COLOR_MAGENTA]

colormap = {
'C' : 5, 'CS': 1,
'S' : 2, 'AS': 1,
'A' : 3, 'AV': 1,
'V' : 4, 'AR': 1,
'R' : 6,
}

class AdvCivTool:
	def __init__(self):
		self.have = [[0]*NumCards for i in xrange(len(CivNames))]
		self.inuse = [False] * len(CivNames)
		self.sel = 0
		self.pro = 0

	def redraw(self, scr):
		s = "-+- Advanced Civilization Tool -+-"
		s = ' '*(40-len(s)/2)+s
		scr.addstr(0,0, s+' '*(80-len(s)), curses.A_BOLD | curses.color_pair(7))

		scr.move(3,0)
		scr.clrtoeol()
		scr.move(2,0)
		scr.clrtoeol()
		for i,n in enumerate(CivNames):
			scr.addstr(' ',0)
			#if not (self.inuse[i] or self.pro == i): continue
			if self.pro == i:
				clr = curses.A_STANDOUT | curses.color_pair(4)
			else:
				clr = curses.color_pair(0)
			n = '%i.%s' % (i+1,n)
			if self.inuse[i]:
				y,x = scr.getyx()
				scr.move(y+1,x+2)
				scr.addstr('%i'%(total(self.have[i])), 0)
				scr.move(y,x)
			scr.addstr(n, clr)

		have = self.have[self.pro]
		for i,hv in enumerate(have):
			val, type, name = Cards[i]

			str = "%2s %*s -> " % (type, -Cards_namewidth, name)
			if hv:
				if Prereqs[i] and not have[Prereqs[i]]:
					str += 'Missing Prereq!'
				else:
					str += ' --'
			else:
				cos = cost(i)
				crd = credit(i,have)
				str += '%3i -%3i = %3i ' % (cos, crd, cos-crd)
			clr = curses.color_pair(colormap[type])
			if i == self.sel: clr |= curses.A_STANDOUT
			if i < NumCards/2:
				scr.addstr(5+i, 2, str, clr)
			else:
				scr.addstr(5+i-NumCards/2, 42, str, clr)
			scr.clrtoeol()
		scr.addstr(NumCards/2+6, 0, "Total = %i" % total(have))
		scr.clrtoeol()

	def main(self, stdscr):
		curses.curs_set(0)
		for i,v in enumerate(colors):
			curses.init_pair(i+1, colors[i], curses.COLOR_BLACK)
		curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_WHITE)

		#curses.init_color(curses.COLOR_MAGENTA, 700, 700, 0)
	
		while True:
			self.redraw(stdscr)
			stdscr.refresh()
			c = stdscr.getch()
			if c == ord(' '):
				self.have[self.pro][self.sel] = 1 - self.have[self.pro][self.sel]
				self.inuse[self.pro] = bool(sum(self.have[self.pro]))
			if c == curses.KEY_DOWN: self.sel = min(NumCards-1, self.sel+1)
			if c == curses.KEY_UP  : self.sel = max(0, self.sel-1)
			if c == curses.KEY_LEFT :
				if self.sel >= NumCards/2: self.sel -= NumCards/2
			if c == curses.KEY_RIGHT:
				if self.sel <= NumCards/2: self.sel += NumCards/2
			if c == curses.KEY_PPAGE:
				self.sel = (self.sel >= NumCards/2 and NumCards/2) or 0
			if c == curses.KEY_NPAGE:
				self.sel = (self.sel >= NumCards/2 and NumCards-1) or NumCards/2-1
			if c == curses.KEY_HOME: self.sel = 0
			if c == curses.KEY_END: self.sel = NumCards-1
			if c >= ord('1') and c <= ord('9'): self.pro = int(c)-ord('1')

if __name__ == '__main__':
	act = AdvCivTool()
	try:
		curses.wrapper(act.main)
	except KeyboardInterrupt:
		print '[2J',
